import { goTo } from '@/modules/move'
import StructureSite from '@/modules/structureSite'
import { getCreepWorking, isCenterNineRoom, isHighWayRoom } from '@/utils/common'
import { QuickStartMemory, QuickerData } from './types'
import { getFreeSpace } from '@/utils/position'
import RoomMap from '@/modules/roomMap'
import { isInterval } from '@/ayaka'
import { remoteObserve } from '../remoteHarvest'
import { getRoleCreeps } from '@/modules/global/clearMemory'
import { CreepRoles } from '@/modules/structures/spawn/types'

let index = 0

/**
 * quicker工作函数
 */
export const quickerWork = function (quickers: Creep[], room: MyRoom, quickStartMemory: QuickStartMemory) {
    const creeps = quickers.filter((creep) => !creep.spawning)
    if (!creeps.length) return

    creeps.forEach((creep) => {
        getCreepWorking(creep)
        delete creep.memory.stand
        if (creep.memory.slack) return

        if (creep.memory.working) {
            // if (creep.room.name !== room.name) {
            //     goTo(creep, new RoomPosition(25, 25, room.name), { range: 23 })
            //     return
            // }

            delete creep.memory.sourceId

            if (!creep.memory.targetId) {
                // 没有container，找spawn
                if (
                    !getRoleCreeps(room.name, CreepRoles.transporter).length ||
                    (creep.ticksToLive && creep.ticksToLive > 700 && !room.container.length)
                ) {
                    const spawns = room.spawn.filter((s) => s.store.getFreeCapacity('energy') > 0)
                    if (spawns.length) {
                        creep.memory.targetId = spawns[0].id
                    }
                }

                if (!creep.memory.targetId) {
                    if (room.controller.level < 2) {
                        creep.memory.targetId = room.controller.id
                    } else {
                        // 找建筑工地
                        const siteTuple = StructureSite.getFirst(room.name, creep)
                        if (!siteTuple) {
                            creep.memory.targetId = room.controller.id
                        } else {
                            const site = Game.getObjectById(siteTuple[1].id as Id<ConstructionSite>)
                            if (!site) {
                                StructureSite.setDone(room.name, siteTuple[0], siteTuple[1].id)
                                return
                            }
                            creep.memory.targetId = site.id
                        }
                    }
                }
            }

            if (!creep.memory.targetId) {
                creep.memory.slack = 7
                return
            }

            const target = Game.getObjectById(
                creep.memory.targetId as Id<StructureSpawn | StructureController | ConstructionSite>,
            )

            if (!target) {
                delete creep.memory.targetId
                return
            }

            if (target instanceof StructureController) {
                if (creep.upgradeController(target) === ERR_NOT_IN_RANGE) {
                    goTo(creep, target.pos, { range: 2 })
                } else {
                    creep.memory.stand = true
                }
            } else if (target instanceof ConstructionSite) {
                if (creep.build(target) === ERR_NOT_IN_RANGE) {
                    goTo(creep, target.pos, { range: 2 })
                } else {
                    creep.memory.stand = true
                }
            } else {
                if (creep.transfer(target, 'energy') === ERR_NOT_IN_RANGE) {
                    goTo(creep, target.pos)
                }
            }
        } else {
            delete creep.memory.targetId

            const data = creep.memory.data as QuickerData

            // 外出寻找能量
            if (quickStartMemory.isOut && !creep.memory.sourceId) {
                if (!data.outRoom) {
                    // 或者出口房间并过滤掉有主房间，中央九房和过道房间
                    const exits = Game.map.describeExits(room.name)
                    const outRooms = Object.keys(exits)
                        .map((direction) => {
                            return { name: exits[direction as ExitKey], direction: parseInt(direction, 10) }
                        })
                        .filter(
                            (r) =>
                                r.name &&
                                !RoomMap.getStats(r.name)?.owner &&
                                !isCenterNineRoom(r.name) &&
                                !isHighWayRoom(r.name) &&
                                Game.map.getRoomStatus(r.name).status === Game.map.getRoomStatus(room.name).status,
                        )

                    if (!outRooms.length) {
                        quickStartMemory.isOut = false
                        return
                    }

                    const outRoom = outRooms[index++ % outRooms.length]
                    data.outRoom = outRoom.name
                }

                const [x, y] = data.sourcePos || [25, 25]

                if (creep.room.name !== data.outRoom) {
                    goTo(creep, new RoomPosition(x, y, data.outRoom!), { range: data.sourcePos ? 1 : 23 })
                    return
                }

                // 观察房间
                RoomMap.statRoom(creep.room)
                // 添加外矿
                if (!creep.memory.ready && Game.cpu.bucket > 200) {
                    remoteObserve(creep, { roomNames: [creep.room.name] } as any)
                    creep.memory.ready = true
                }

                if (RoomMap.getStats(data.outRoom)?.owner) {
                    delete data.outRoom
                    delete data.sourceId
                    delete data.sourcePos
                    return
                }

                if (!data.sourceId || !data.sourcePos) {
                    const sources = creep.room.find(FIND_SOURCES).filter((s) => s.energy > 0)
                    if (!sources.length) {
                        delete data.outRoom
                        delete data.sourceId
                        delete data.sourcePos
                        return
                    }

                    const source =
                        (sources.length === 1 ? sources[0] : creep.pos.findClosestByPath(sources)) || sources[0]
                    data.sourceId = source.id
                    data.sourcePos = [source.pos.x, source.pos.y]
                }

                const sourcePos = new RoomPosition(data.sourcePos[0], data.sourcePos[1], data.outRoom)
                if (creep.pos.getRangeTo(sourcePos) > 1) {
                    goTo(creep, sourcePos)
                    return
                }

                const source = Game.getObjectById(data.sourceId as Id<Source>)
                if (!source || source.energy <= 0) {
                    delete data.sourceId
                    delete data.sourcePos
                    return
                }

                creep.harvest(source)
                creep.memory.stand = true
            } else {
                if (creep.room.name !== room.name) {
                    goTo(creep, new RoomPosition(25, 25, room.name), { range: 23 })
                    return
                }

                if (!creep.memory.sourceId) {
                    if (creep.ticksToLive! < 300) {
                        if (quickStartMemory.isOut === undefined) {
                            quickStartMemory.isOut = true
                            return
                        }
                    }
                    const sources = room
                        .find(FIND_SOURCES)
                        .filter((s) => s.energy > 0)
                        .sort(
                            (a, b) =>
                                getFreeSpace(b.pos, { ignoreCreep: false }).length -
                                getFreeSpace(a.pos, { ignoreCreep: false }).length,
                        )
                    const source = sources[0]
                    // 不存在 source 或者 harvester 的数量和 source 的数量相等并且 source 的空位为 0
                    if (
                        !source ||
                        (getRoleCreeps(room.name, CreepRoles.harvester).length >= sources.length &&
                            getFreeSpace(source.pos, { ignoreCreep: false }).length === 0)
                    ) {
                        if (quickStartMemory.isOut === undefined) quickStartMemory.isOut = true
                        return
                    }
                    creep.memory.sourceId = source.id
                }

                const source = Game.getObjectById(creep.memory.sourceId as Id<Source>)
                if (!source || source.energy <= 0) {
                    delete creep.memory.sourceId
                    return
                }

                if (creep.pos.getRangeTo(source) > 1) {
                    if (isInterval(7) && !getFreeSpace(source.pos, { ignoreCreep: false }).length) {
                        delete creep.memory.sourceId
                        return
                    }
                    goTo(creep, source.pos)
                    return
                }

                creep.harvest(source)
                creep.memory.stand = true
            }
        }
    })
}
